from enum import Enum
from typing import TYPE_CHECKING, Literal, Optional

from sqlalchemy import Boolean, Column, String
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship

from app.db.base_class import Base
from .link import user_group_association
from .archivable import Archivable

if TYPE_CHECKING:
    from .file import File  # noqa: F401
    from .item import Item  # noqa: F401


class Role(str, Enum):
    ADMIN = "admin"             # 平台的管理员，拥有最高权限，可以对其他用户进行管理。
    MODERATOR = "moderator"     # 平台的内容审查员，负责审查用户上传的内容。
    CUSTOMER = "customer"       # 平台的用户，可以进行普通的操作。


class Provider(str, Enum):
    EMAIL = "email"
    GOOGLE = "google"
    FACEBOOK = "facebook"
    GITHUB = "github"


# 修改此设置以匹配您在项目中使用的 SSO 提供程序
SSOProvider = Literal[Provider.GOOGLE, Provider.FACEBOOK, Provider.GITHUB]


class User(Base, Archivable):
    # 认证
    email = Column(String, unique=True, index=True, nullable=False)
    password_hash = Column(String)
    role = Column(String, default=Role.CUSTOMER, nullable=False)
    confirmed = Column(Boolean, default=False)
    sso_confirmation_code = Column(String)
    # 个人信息
    first_name = Column(String, default="")
    last_name = Column(String, default="")
    phone = Column(String)
    address = Column(String)
    city = Column(String)
    postcode = Column(String)
    state = Column(String)
    provider = Column(String, default=Provider.EMAIL, nullable=False)
    sso_provider_id = Column(String, index=True)

    profile_pic = relationship("File", backref="user", uselist=False, cascade="all, delete")
    items = relationship("Item", backref="user", lazy="dynamic", cascade="all, delete")
    groups = relationship(
        'Group',
        secondary=user_group_association,
        back_populates="users"
    )

    @hybrid_property
    def is_admin(self) -> bool:
        return self.role == Role.ADMIN

    @hybrid_property
    def is_moderator(self) -> bool:
        return self.role == Role.MODERATOR

    @hybrid_property
    def is_customer(self) -> bool:
        return self.role == Role.CUSTOMER

    @hybrid_property
    def full_name(self) -> str:
        return f"{self.first_name} {self.last_name}"

    @hybrid_property
    def profile_picture_url(self) -> Optional[str]:
        return (
            self.profile_pic.user_profile_pic_url
            if self.profile_pic is not None
            else None
        )
